#include "CUserPartner.h"
#include "CPartnerCfg.h"
#include "../mainctrl.h"
#include "../skill/CSkillMgr.h"
#include "../simpleconfig/CRoleConfigMgr.h"

/************************************************************************/
/*                    CPartnerUnit                                      */
/************************************************************************/
int CPartnerUnit::InitByCfg(CPartnerCfgData& stCfgData)
{
    int iRet = 0;
    unsigned int uiSkillID = 0;

    _shResID = stCfgData._shResID;

    _stAttr.Clear();

    _stAttr.SetAttr(BASE_ATTR_INT, stCfgData._iInt);
    _stAttr.SetAttr(BASE_ATTR_VIT, stCfgData._iVit);
    _stAttr.SetAttr(BASE_ATTR_STR, stCfgData._iStr);
    _stAttr.SetAttr(BASE_ATTR_AGI, stCfgData._iAgi);

    //技能相关
    //_stSpeSkillEff.Clear();
    //_stLockSkillEff.Clear();
    _stNormalSkill.Clear();
    _stMagicSkill.Clear();

#if 0
    //按照能力来做
    iIndex = stSkillMgr.FindSkillEffCfg(stCfgData._iSpeEffect);
    if (iIndex >= 0)
    {
        CSkillEffCfgData& stSpeSkillEffCfg = stSkillMgr.GetSkillEffCfg(iIndex);
        iRet = _stSpeSkillEff.InitByEffCfg(stSpeSkillEffCfg);
        CT_RETURN(iRet);
    }

    iIndex = stSkillMgr.FindSkillEffCfg(stCfgData._iLockEffect);
    if (iIndex >= 0)
    {
        CSkillEffCfgData& stLockSkillEffCfg = stSkillMgr.GetSkillEffCfg(iIndex);
        iRet = _stLockSkillEff.InitByEffCfg(stLockSkillEffCfg);
        CT_RETURN(iRet);
    }
#endif

    uiSkillID = stCfgData._uiNormalSkiID;
    if (uiSkillID > 0)
    {
        iRet = CMainCtrl::m_pstMain->m_stSkillMgr.GetSkillByID(_stNormalSkill,
            uiSkillID, CSkill::SKILL_TYPE_NORMAL);
        CT_RETURN(iRet);
    }

    uiSkillID = stCfgData._uiMagicSkiID;
    if (uiSkillID > 0)
    {
        iRet = CMainCtrl::m_pstMain->m_stSkillMgr.GetSkillByID(_stMagicSkill,
            uiSkillID, CSkill::SKILL_TYPE_MAGIC);
        CT_RETURN(iRet);
    }

    return 0;
}

int CPartnerUnit::InitByListData(CPartnerCfgData& stCfgData,
        CPartnerListData& stListData)
{
    return InitByCfg(stCfgData);
}

int CPartnerUnit::CalcExtAttr(CPartnerCfgData& stCfgData,
        CPartnerActData& stActData)
{
    return CMainCtrl::m_pstMain->m_stPartnerMgr.CalcExtAttr(stCfgData, _stAttr,
        stActData._shLevel);
}

int CPartnerUnit::ReCalcExtAttr(CPartnerActData& stActData,
        CPlayerBaseInfo& stPlayerBase, CPlayerDetailInfo& stPlayerDetail,
        CPlayerOnlineData& stPlayerOnline,
        CPlayerDetailInfoEx1& stPlayerDetailEx1, bool bNotifyPartnerInfo,
        bool bSendTeamFighting)
{
    //这里作为计算的起点

    int iRet = 0;
    int iIndex = CMainCtrl::m_pstMain->m_stPartnerMgr.FindPartnerCfg(_shResID);
    if (iIndex < 0)
    {
        return ERROR_PARTNER_EMPTY_CFG;
    }
    CPartnerCfgData& stCfgData =
        CMainCtrl::m_pstMain->m_stPartnerMgr.GetPartnerCfg(iIndex);

    _stAttr.Clear();

    //伙伴升级获得的基础属性 以及不可逆二级属性
    iRet = CalcExtAttr(stCfgData, stActData);
    CT_RETURN(iRet);

    //伙伴默认的反击率
    if (_stAttr.GetAttr(EXT_ATTR_FIGHT_BACK) < ATTR_ROLE_DEFAULT_FIGHT_BACK)
    {
        iRet = _stAttr.AddAttr(EXT_ATTR_FIGHT_BACK,
            ATTR_ROLE_DEFAULT_FIGHT_BACK);
        CT_RETURN(iRet);
    }

    //装备提升的二级属性
    iRet = CMainCtrl::m_pstMain->m_stEquipMgr.GetEquipAttr(
        stPlayerOnline._stUserEquip, _shResID, _stAttr);
    if (iRet){CT_ERROR(("%u %d", stPlayerBase._uiGID,iRet));}

    //魔药的属性
    iRet = CMainCtrl::m_pstMain->m_stDrugMgr.GetDrugAttr(stPlayerDetail,
        _shResID, _stAttr);
    if (iRet){CT_ERROR(("%u %d", stPlayerBase._uiGID,iRet));}

    //家族技能的二级属性    
    iRet = CMainCtrl::m_pstMain->m_stClanMgr.GetSkillAttr(
        stPlayerDetail._stUserClan, _stAttr);
    if (iRet){CT_ERROR(("%u %d", stPlayerBase._uiGID,iRet));}

    //上课属性
    CPlayerAttr stLessonAttr;
    CMainCtrl::m_pstMain->m_stLessonMgr.GetAttr(stPlayerDetail._stUserLessonData, stLessonAttr);
    _stAttr += stLessonAttr;

    //装备的套装属性
    CPlayerAttr stSuiteAttr;
    iRet = CMainCtrl::m_pstMain->m_stEquipMgr.GetSuiteAttr(
        stPlayerOnline._stUserEquip, _shResID, stSuiteAttr);
    if (iRet){CT_ERROR(("%u %d", stPlayerBase._uiGID,iRet));}
    _stAttr += stSuiteAttr;

    //卡片属性
    CPlayerAttr stCardAttr;
    iRet = CMainCtrl::m_pstMain->m_stCardMgr.GetCardAttr(
        stPlayerOnline._stUserCard, _shResID, stPlayerDetail, stCardAttr);
    if (iRet){CT_ERROR(("%u %d", stPlayerBase._uiGID,iRet));}
    _stAttr += stCardAttr;

    //秘宝二级属性
    iRet = CMainCtrl::m_pstMain->m_stTreasureMgr.CalcTreasureAttr(
        stPlayerDetail, _stAttr, GAME_OBJ_TYPE_PARTNER, _shResID);
    if (iRet){CT_ERROR(("%u %d", stPlayerBase._uiGID,iRet));}

    //宠物属性
    if (stPlayerOnline._stUserPet.PetIsActive())
    {
        CPlayerAttr stPetAttr;
        iRet = CMainCtrl::m_pstMain->m_stPetMgr.GetPetAttr(stPlayerOnline._stUserPet,
            stPetAttr);
        if (iRet){CT_ERROR(("%u %d", stPlayerBase._uiGID,iRet));}
        _stAttr += stPetAttr;
    }

    //坐骑属性
    CPlayerAttr stMountAttr;
    int iMatrixPos = CMainCtrl::m_pstMain->m_stMatrixMgr.GetMatrixRtoLPos(
            stPlayerBase, stPlayerDetail, GAME_OBJ_TYPE_PARTNER, _shResID);
    if (iMatrixPos > 0)
    {
        iRet = CMainCtrl::m_pstMain->m_stMountMgr.GetMountAttr(
            stPlayerDetailEx1._stMount, iMatrixPos, stMountAttr);
        if (iRet){CT_ERROR(("%u %d %d", stPlayerBase._uiGID,_shResID,iRet));}
        _stAttr += stMountAttr;
#ifdef _DEBUG
        CT_BATTLE(("伙伴(%d)阵位(%d)坐骑属性加成:",_shResID,iMatrixPos));
        CMainCtrl::m_pstMain->m_stRoleMgr.DumpOnlineRoleInfo(stMountAttr);
#endif
    }

    //魔晶修正基础属性. ( !!! 注意: 魔晶会对属性按百分比进行修正, "新增系统" 请跟策划确认属性修正的计算公式)
    iRet = CMainCtrl::m_pstMain->m_stEquipMgr.GetCrystalAttr(stPlayerOnline._stUserEquip, _shResID, true, _stAttr);
    if (iRet){CT_ERROR(("%u %d", stPlayerBase._uiGID,iRet));}

    //这个是基础属性换算为二级属性需要放在各种基础属性加成之后
    iRet = CMainCtrl::m_pstMain->m_stRoleMgr.CalcCareerBaseToExtAttr(_stAttr, stCfgData.GetCareer());
    if (iRet){CT_ERROR(("%u %d", stPlayerBase._uiGID,iRet));}
#if 0
    //魔晶修正二级属性. ( !!! 注意: 魔晶会对属性按百分比进行修正, "新增系统" 请跟策划确认属性修正的计算公式)
    iRet = CMainCtrl::m_pstMain->m_stEquipMgr.GetCrystalAttr(stPlayerOnline._stUserEquip, _shResID, false, _stAttr);
    if (iRet){CT_ERROR(("%u %d", stPlayerBase._uiGID,iRet));}
#endif
    //不被魔晶修正的二级属性 (请添加在下面).
    //角色先手值受装备强化等级卡片等级的修正
    iRet = CMainCtrl::m_pstMain->m_stRoleMgr.AddObjTurnOrder(_stAttr,
        GAME_OBJ_TYPE_PARTNER, _shResID, stPlayerDetail, stPlayerOnline);
    if (iRet){CT_ERROR(("%u %d", stPlayerBase._uiGID,iRet));}

    //魔晶潜能
    CPlayerAttr stPotenAttr;
    iRet = CMainCtrl::m_pstMain->m_stEquipMgr.GetPotenAttr(stPlayerOnline._stUserEquip, stPlayerBase._ucCrystalPotenLevel, _shResID, stPotenAttr);
    if (iRet) {CT_ERROR(("%u %d %d", stPlayerBase._uiGID, _shResID,iRet));}
    _stAttr += stPotenAttr;

    //不被魔晶修正的二级属性 (请添加在上面).

    if (stPlayerOnline._bIsInitFinish)
    {
        //重新计算伙伴战斗力
        CMainCtrl::m_pstMain->m_stRoleMgr.CalcObjFighting(stPlayerDetail._uiGID,
            GAME_OBJ_TYPE_PARTNER, _shResID);

        //重新计算队伍战斗力
        CMainCtrl::m_pstMain->m_stMatrixMgr.CalcMainFighting(stPlayerDetail, stPlayerOnline);

        if (bNotifyPartnerInfo)
        {
            CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stPlayerOnline._uiGID,
                NOTIFY_PARTNER_INFO, _shResID);
        }

        if (bSendTeamFighting &&
            CMainCtrl::m_pstMain->m_stMatrixMgr.PartnerInMainMatrix(
                stPlayerDetail, _shResID))
        {
            CMainCtrl::m_pstMain->m_stMatrixMgr.SendMatrixFightingToFront(
                stPlayerBase, stPlayerDetail, stPlayerOnline);
        }
    }

    return 0;
}

int CPartnerUnit::InitByActData(CPartnerCfgData& stCfgData,
        CPartnerActData& stActData, CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        CPlayerDetailInfoEx1& stPlayerDetailEx1)
{
    int iRet = 0;
    unsigned int uiSkillID = 0;

    _shResID = stActData._shResID;

    _stAttr.Clear();
    _stAttr.SetAttr(BASE_ATTR_INT, stCfgData._iInt);
    _stAttr.SetAttr(BASE_ATTR_VIT, stCfgData._iVit);
    _stAttr.SetAttr(BASE_ATTR_STR, stCfgData._iStr);
    _stAttr.SetAttr(BASE_ATTR_AGI, stCfgData._iAgi);

    //技能相关
    //_stSpeSkillEff.Clear();
    //_stLockSkillEff.Clear();
    _stNormalSkill.Clear();
    _stMagicSkill.Clear();

#if 0
    //按照能力来做
    iIndex = stSkillMgr.FindSkillEffCfg(stActData._iSpeID);
    if (iIndex >= 0)
    {
        CSkillEffCfgData& stSpeSkillEffCfg = stSkillMgr.GetSkillEffCfg(iIndex);
        iRet = _stSpeSkillEff.InitByEffCfg(stSpeSkillEffCfg);
        CT_RETURN(iRet);
    }

    iIndex = stSkillMgr.FindSkillEffCfg(stActData._iLockID);
    if (iIndex >= 0)
    {
        CSkillEffCfgData& stLockSkillEffCfg = stSkillMgr.GetSkillEffCfg(iIndex);
        iRet = _stLockSkillEff.InitByEffCfg(stLockSkillEffCfg);
        CT_RETURN(iRet);
    }
#endif

    uiSkillID = stCfgData._uiNormalSkiID;
    if (uiSkillID > 0)
    {
        iRet = CMainCtrl::m_pstMain->m_stSkillMgr.GetSkillByID(_stNormalSkill,
            uiSkillID, CSkill::SKILL_TYPE_NORMAL);
        CT_RETURN(iRet);
    }

    uiSkillID = stCfgData._uiMagicSkiID;
    if (uiSkillID > 0)
    {
        iRet = CMainCtrl::m_pstMain->m_stSkillMgr.GetSkillByID(_stMagicSkill,
            uiSkillID, CSkill::SKILL_TYPE_MAGIC);
        CT_RETURN(iRet);
    }

    return ReCalcExtAttr(stActData, stPlayerBase, stPlayerDetail,
        stPlayerOnline, stPlayerDetailEx1, false, false);
}

int CPartnerUnit::TransToListData(CPartnerActData& stActData,
        CPartnerListData& stListData)
{
    stListData._shResID = stActData._shResID;
    stListData._shLevel = stActData._shLevel;
    stListData._iFavor = stActData._iFavor;
    stListData._i64Exp = stActData._i64Exp;

    stListData._stDrugData = stActData._stDrugData;

    return 0;
}

int CPartnerUnit::TransToActData(CPartnerActData& stActData)
{
    stActData._shResID = _shResID;

    return 0;
}

int CPartnerUnit::TransToActData(CPartnerListData& stListData,
        CPartnerActData& stActData)
{
    stActData._shResID = stListData._shResID;
    stActData._shLevel = stListData._shLevel;
    stActData._iFavor = stListData._iFavor;
    stActData._i64Exp = stListData._i64Exp;

    stActData._stDrugData = stListData._stDrugData;


    return 0;
}

/************************************************************************/
/*                    CUserPartner                                      */
/************************************************************************/
bool CUserPartner::IsOnlinePartner(short shResID)
{
    for (int i = 0; i < _astOnlineData.Size(); ++i)
    {
        if (shResID == _astOnlineData[i]._shResID)
        {
            return true;
        }
    }

    return false;
}

int CUserPartner::AddPartner(CPartnerUnit& stPartnerUnit)
{
    int iRet = _astOnlineData.AddOneItem(stPartnerUnit);
    if (iRet < 0)
    {
        return iRet;
    }
    return 0;
}

int CUserPartner::DelPartner(short shResID)
{
    for (int i = 0; i < _astOnlineData.Size(); )
    {
        if (shResID == _astOnlineData[i]._shResID)
        {
            int iRet = _astOnlineData.DelOneItem(i);
            if (iRet < 0)
            {
                return iRet;
            }
        }
        else
        {
            ++i;
        }
    }

    return 0;
}

int CUserPartner::FindPartner(short shResID)
{
    for (int i = 0; i < _astOnlineData.Size(); ++i)
    {
        if (shResID == _astOnlineData[i]._shResID)
        {
            return i;
        }
    }

    return -1;
}

int CUserPartner::AllReCalcExtAttr(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        CPlayerDetailInfoEx1& stPlayerDetailEx1)
{
    int iRet = 0;
    for (int i = 0; i < stPlayerDetail._stUserPartner._astActData.Size(); ++i)
    {
        iRet = ReCalcExtAttr(
            stPlayerDetail._stUserPartner._astActData[i]._shResID, stPlayerBase,
            stPlayerDetail, stPlayerOnline, stPlayerDetailEx1, true, false);
        if (iRet)
        {
            CT_ERROR(("%d, %d",
                stPlayerDetail._stUserPartner._astActData[i]._shResID,iRet));
        }
    }

    return 0;
}

int CUserPartner::ReCalcExtAttr(short shResID, CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        CPlayerDetailInfoEx1& stPlayerDetailEx1, bool bNotifyPartnerInfo,
        bool bSendTeamFighting)
{
    int iRet = 0;
    int iIndex = FindPartner(shResID);
    if (iIndex < 0)
    {
        return ERROR_PARTNER_NOT_IN_ACT;
    }
    CPartnerUnit& stPartnerUnit = GetPartner(iIndex);

    iIndex = stPlayerDetail._stUserPartner.FindActData(shResID);
    if (iIndex < 0)
    {
        return ERROR_PARTNER_NOT_IN_ACT;
    }
    CPartnerActData& stActData =
        stPlayerDetail._stUserPartner.GetPartnerActData(iIndex);

    iRet = stPartnerUnit.ReCalcExtAttr(stActData, stPlayerBase, stPlayerDetail,
        stPlayerOnline, stPlayerDetailEx1, bNotifyPartnerInfo,
        bSendTeamFighting);
    CT_RETURN(iRet);

    return 0;
}

int CUserPartner::UpLevel(short shResID, int iAddExp,
        CPlayerBaseInfo& stPlayerBase, CPlayerDetailInfo& stPlayerDetail,
        CPlayerOnlineData& stPlayerOnline,
        CPlayerDetailInfoEx1& stPlayerDetailEx1)
{
    if (iAddExp < 0)
    {
        return ERROR_PARTNER_EXP_DATA;
    }

    int iIndex = FindPartner(shResID);
    if (iIndex < 0)
    {
        return ERROR_PARTNER_NOT_IN_ACT;
    }
    CPartnerUnit& stPartnerUnit = GetPartner(iIndex);

    iIndex = stPlayerDetail._stUserPartner.FindActData(shResID);
    if (iIndex < 0)
    {
        return ERROR_PARTNER_NOT_IN_ACT;
    }
    CPartnerActData& stActData =
        stPlayerDetail._stUserPartner.GetPartnerActData(iIndex);

    short shOldPartnerLvl = stActData._shLevel;
    int iRet = CMainCtrl::m_pstMain->m_stPartnerMgr.DealUpLevel(
        stActData._shLevel, stPlayerBase._shLevel, iAddExp, stActData._i64Exp);
    CT_RETURN(iRet);

    //触发任务
    CMainCtrl::m_pstMain->m_stTaskMgr.TriggerDoSomeOpt(
        stPlayerOnline._stUserTask,
        (TASK_OPT_ID_116 * 1000 + shResID) * 1000 + stActData._shLevel, 1); //将伙伴X等级提升至Y级
    CMainCtrl::m_pstMain->m_stTaskMgr.TriggerDoSomeOpt(
        stPlayerOnline._stUserTask,
        TASK_OPT_ID_124 * 1000 + stActData._shLevel, 1);

    if (stActData._shLevel > shOldPartnerLvl)
    {
        iRet = stPartnerUnit.ReCalcExtAttr(stActData, stPlayerBase,
            stPlayerDetail, stPlayerOnline, stPlayerDetailEx1, true, false);
    }

    return iRet;
}

int CUserPartner::AddExp(short shResID, int iAddExp,
        CPlayerBaseInfo& stPlayerBase, CPlayerDetailInfo& stPlayerDetail,
        CPlayerOnlineData& stPlayerOnline,
        CPlayerDetailInfoEx1& stPlayerDetailEx1)
{
    return UpLevel(shResID, iAddExp, stPlayerBase, stPlayerDetail,
        stPlayerOnline, stPlayerDetailEx1);
}

